#include "widget.h"
#include <QPainter>
#include <QMouseEvent>
#include <QScreen>
#include <QApplication>

PetWidget::PetWidget(QWidget *parent) : QWidget(parent) {
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground);

    startLoadingFrames();

    animationTimer.setInterval(100);
    connect(&animationTimer, &QTimer::timeout, this, &PetWidget::updateAnimation);
}

void PetWidget::paintEvent(QPaintEvent *) {
    if (!framesLoaded) return;

    QPixmap buffer(size());
    buffer.fill(Qt::transparent);
    QPainter bufferPainter(&buffer);
    bufferPainter.setRenderHint(QPainter::Antialiasing);

    if (currentState == State::Idle && !idleFrames.isEmpty()) {
        currentFrame %= idleFrames.size();
        QSize currentSize = idleSizes[currentFrame];
        if (size() != currentSize) {
            QPoint center = geometry().center();
            setFixedSize(currentSize);
            move(center - QPoint(currentSize.width() / 2, currentSize.height() / 2));
        }
        bufferPainter.drawPixmap(0, 0, idleFrames[currentFrame]);
    } else if (currentState == State::Clicked && !clickFrames.isEmpty()) {
        currentFrame %= clickFrames.size();
        QSize currentSize = clickSizes[currentFrame];
        if (size() != currentSize) {
            QPoint center = geometry().center();
            setFixedSize(currentSize);
            move(center - QPoint(currentSize.width() / 2, currentSize.height() / 2));
        }
        bufferPainter.drawPixmap(0, 0, clickFrames[currentFrame]);
    }

    QPainter windowPainter(this);
    windowPainter.drawPixmap(0, 0, buffer);
}

void PetWidget::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
#else
        dragPosition = event->globalPos() - frameGeometry().topLeft();
#endif
        currentState = State::Clicked;
        currentFrame = 0;
        QTimer::singleShot(800, this, &PetWidget::resetToIdle);
        update();
    }
}

void PetWidget::mouseMoveEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
        QPoint newPos = event->globalPosition().toPoint() - dragPosition;
#else
        QPoint newPos = event->globalPos() - dragPosition;
#endif
        restrictToScreen(newPos);
        move(newPos);
    }
}

void PetWidget::updateAnimation() {
    if (!framesLoaded) return;

    switch (currentState) {
    case State::Idle:
        currentFrame = (currentFrame + 1) % idleFrames.size();
        break;
    case State::Clicked:
        if (currentFrame < clickFrames.size() - 1) {
            currentFrame++;
        }
        break;
    }
    update();
}

void PetWidget::resetToIdle() {
    currentState = State::Idle;
    currentFrame = 0;
}

void PetWidget::loadFrames() {
    idleFrames.clear();
    idleSizes.clear();
    clickFrames.clear();
    clickSizes.clear();

    initAnimationFrame(":/images/kongxian", 6, idleFrames, idleSizes);
    initAnimationFrame(":/images/paodong", 8, clickFrames, clickSizes);

    if (!idleSizes.isEmpty()) {
        setFixedSize(idleSizes.first());
    }
    framesLoaded = true;
}

void PetWidget::initAnimationFrame(const QString &framePrefix, int frameCount, QVector<QPixmap> &frames, QVector<QSize> &sizes) {
    for (int i = 1; i <= frameCount; ++i) {
        QString path = framePrefix + QString::number(i) + ".png";
        QPixmap pix(path);
        if (!pix.isNull()) {
            frames.append(pix);
            sizes.append(pix.size());
        }
    }
}

void PetWidget::startLoadingFrames() {
    loadFrames();
    emit loadFinished(true);
    animationTimer.start();
}

void PetWidget::moveToScreenCenter() {
    QScreen *screen = QApplication::primaryScreen();
    QRect rect = screen->availableGeometry();
    move(rect.center() - QPoint(width() / 2, height() / 2));
}

void PetWidget::restrictToScreen(const QPoint &pos) {
    QScreen *screen = QApplication::primaryScreen();
    QRect availableRect = screen->availableGeometry();
    int newX = qBound(availableRect.left(), pos.x(), availableRect.right() - width());
    int newY = qBound(availableRect.top(), pos.y(), availableRect.bottom() - height());
    move(newX, newY);
}
